<!DOCTYPE html>
<html>
<head>
        <meta charset="UTF-8">
        <title>Gmetad's metrics using Flot Charts</title>
        <link type="text/css" rel="stylesheet" href="css/stylesheet.css">
        <script language="javascript" type="text/javascript" src="lib/jquery.js"></script>
        <script language="javascript" type="text/javascript" src="lib/jquery.flot.js"></script>
        <script language="javascript" type="text/javascript" src="lib/jquery.flot.time.js"></script>

        <script type="text/javascript">
            var sent_data, sent_time_data, cpu_data, poll_data, poll_time_data, recv_data, sumrz_data, sumrz_time_data, req_data, req_time_data;
            /*
                metricsInternal is the graph update speed.
                lastTimeInterval is the "Last" line update speed.
            */
            var metricsInterval = 60000, lastTimeInterval = 5000;//ms
            var metricsTimerId = null, lastTimeTimerId = null;
            var timespawn;
            var tmpsentallvar, tmprrdtoolvar, tmprrdcachedvar, tmpgraphitevar, tmpmemcachedvar, tmpriemannvar;
            var tmppollokvar, tmppollfailvar, tmpsumrzvar, tmpreqallvar, tmpinteractivevar, tmpxmlvar;
            var tmprecvvar, tmpsumrzclustvar, tmpsumrzrootvar, tmppollmissvar;

            function binder(name){
                $("#" + name).bind("plothover", function (event, pos, item) {
                    if (item) {
                        var x = item.datapoint[0],
                                y = item.datapoint[1].toFixed(2);
                        $("#tooltip").html(new Date(x) + " Value: " + y)
                            .css({top: item.pageY+5, left: item.pageX+5,
                                'background-color': '#ccc',
                                'font-family': 'Arial, sans-serif;',
                                'font-size': '0.8em',
                                opacity: 0.9
                            })
                            .fadeIn(200);
                    } else {
                        $("#tooltip").hide();
                    }
                });
            }
            function setVars(){
                timespawn = retrieveDropVal("timespawn") * 60000; //mins
                sent_data = [[], [], [], [], [], [], []];
                sent_data[0] = [{ data: sent_data[1], label: "All"}, { data: sent_data[2], label: "RRDtool"},
                { data: sent_data[3], label: "RRDcached"}, { data: sent_data[4], label: "Graphite"},
                { data: sent_data[5], label: "Memcached"}, { data: sent_data[6], label: "Riemann"}];
                
                sent_time_data = [[], [], [], [], [], [], []];
                sent_time_data[0] = [{ data: sent_time_data[1], label: "All"}, { data: sent_time_data[2], label: "RRDtool"},
                { data: sent_time_data[3], label: "RRDcached"}, { data: sent_time_data[4], label: "Graphite"},
                { data: sent_time_data[5], label: "Memcached"}, { data: sent_time_data[6], label: "Riemann"}];
                
                cpu_data = [[], [], [], [], []];
                cpu_data[0] = [{ data: cpu_data[1], label: "User"}, { data: cpu_data[2], label: "Nice"},
                { data: cpu_data[3], label: "System"}, { data: cpu_data[4], label: "Idle"}];
                
                poll_data = [[], [], [], []];
                poll_data[0] = [{ data: poll_data[1], label: "Ok"}, { data: poll_data[2], label: "Failed"},
                { data: poll_data[3], label: "Misses"}];
                
                poll_time_data = [[], [], []];
                poll_time_data[0] = [{ data: poll_time_data[1], label: "Ok"}, { data: poll_time_data[2], label: "Failed"}];
                
                recv_data = [[], []];
                recv_data[0] = [{ data: recv_data[1], label: "Metrics/min"}];
                
                sumrz_data = [[], [], []];
                sumrz_data[0] = [{ data: sumrz_data[1], label: "Cluster"}, { data: sumrz_data[2], label: "Root"}];
                
                sumrz_time_data = [[], []];
                sumrz_time_data[0] = [{ data: sumrz_time_data[1], label: "Time"}];
                
                req_data = [[], [], [], []];
                req_data[0] = [{ data: req_data[1], label: "All"}, { data: req_data[2], label: "Interactive"},
                { data: req_data[3], label: "Xml"}];
                
                req_time_data = [[], [], [], []];
                req_time_data[0] = [{ data: req_time_data[1], label: "All"}, { data: req_time_data[2], label: "Interactive"},
                { data: req_time_data[3], label: "Xml"}];
                
                tmpsentallvar = [0, 0]; tmprrdtoolvar = [0, 0];
                tmprrdcachedvar = [0, 0]; tmpgraphitevar = [0, 0];
                tmpmemcachedvar = [0, 0]; tmpriemannvar = [0, 0];
                tmppollokvar = [0, 0]; tmppollfailvar = [0, 0];
                tmprecvvar = 0;
                tmpsumrzclustvar = 0; tmpsumrzrootvar = 0;
                tmpsumrzvar = 0; tmpreqallvar = [0, 0];
                tmpinteractivevar = [0, 0]; tmpxmlvar = [0, 0];
                tmppollmissvar = 0;
            }
            
        function drawChart(name, metrics_data){
            var last_time = metrics_data[1][metrics_data[1].length - 1][0].getTime() - timespawn;
            var i = 0;
            for(;i<metrics_data[1].length;i++){
                if(last_time <= metrics_data[1][i][0].getTime()){
                    break;
                }
            }
            for(var j=1; j<metrics_data[0].length; j++){
                metrics_data[j].splice(0,i);//array is sorted!
            }
            
            var plot = $.plot("#" + name, metrics_data[0],
            {
                series: {
                    lines: {
                        show: true
                    },
                    points: {
                        show: true
                    }
                },
                grid: {
                    hoverable: true,
                    clickable: true
                },
                xaxis: {
                    mode: "time",
                    timezone: "browser",
                    min: metrics_data[1][0][0].getTime(),
                    max: metrics_data[1][0][0].getTime() + timespawn
                },
                yaxis: {
                    min: 0
                },
                legend:{
                    backgroundOpacity: 0.5,
                    noColumns: 0,
                    backgroundColor: "white",
                    position: "nw"
                }
            });
            binder(name);
        }

        /* Two different ajax calls are needed here so that there are no conflicts */
        function getMetrics(){
            var Gmetad = "http://" + window.location.hostname + ":8652/status";
            $.ajax({
                type: "GET",
                url: Gmetad,
                dataType: "jsonp",
                crossDomain: true,
                contentType: "application/json",
                jsonpCallback: "jsonCallback",
                error: function(data, textStatus, jqXHR) { alert("Update crashed, please reload the page..."); console.log(textStatus + " " + jqXHR.responseText);}
                /* If the logged error is "parsererror undefined", then the ajax() call couldn't parse the json data
                because there was a conflict with another call to ajax(), and sometimes the metrics won't update anymore. */
            });
        }

        function getLastTimes(){
            var Gmetad = "http://" + window.location.hostname + ":8652/status";
            $.ajax({
                type: "GET",
                url: Gmetad,
                dataType: "jsonp",
                crossDomain: true,
                contentType: "application/json",
                jsonpCallback: "last_timeCallback",
                error: function(data, textStatus, jqXHR) { alert("Update crashed, please reload the page..."); console.log(textStatus + " " + jqXHR.responseText);}
                /* If the logged error is "parsererror undefined", then the ajax() call couldn't parse the json data
                because there was a conflict with another call to ajax(), and sometimes the metrics won't update anymore. */
            });
        }
        function jsonCallback(data){
                sent_data[1].push([new Date(data["stattime"]), tmpsentallvar[0] != 0 ? (data["metrics"]["sent"]["all"]["num"] - tmpsentallvar[0]) : 0]);
                sent_data[2].push([new Date(data["stattime"]), tmprrdtoolvar[0] != 0 ? (data["metrics"]["sent"]["rrdtool"]["num"] - tmprrdtoolvar[0]) : 0]);
                sent_data[3].push([new Date(data["stattime"]), tmprrdcachedvar[0] != 0 ? (data["metrics"]["sent"]["rrdcached"]["num"] - tmprrdcachedvar[0]) : 0]);
                sent_data[4].push([new Date(data["stattime"]), tmpgraphitevar[0] != 0 ? (data["metrics"]["sent"]["graphite"]["num"] - tmpgraphitevar[0]) : 0]);
                sent_data[5].push([new Date(data["stattime"]), tmpmemcachedvar[0] != 0 ? (data["metrics"]["sent"]["memcached"]["num"] - tmpmemcachedvar[0]) : 0]);
                sent_data[6].push([new Date(data["stattime"]), tmpriemannvar[0] != 0 ? (data["metrics"]["sent"]["riemann"]["num"] - tmpriemannvar[0]) : 0]);
                drawChart('Sent', sent_data);

                sent_time_data[1].push([new Date(data["stattime"]), tmpsentallvar[1] != 0 ? (data["metrics"]["sent"]["all"]["totalMillis"] - tmpsentallvar[1]) : 0]);
                sent_time_data[2].push([new Date(data["stattime"]), tmprrdtoolvar[1] != 0 ? (data["metrics"]["sent"]["rrdtool"]["totalMillis"] - tmprrdtoolvar[1]) : 0]);
                sent_time_data[3].push([new Date(data["stattime"]), tmprrdcachedvar[1] != 0 ? (data["metrics"]["sent"]["rrdcached"]["totalMillis"] - tmprrdcachedvar[1]) : 0]);
                sent_time_data[4].push([new Date(data["stattime"]), tmpgraphitevar[1] != 0 ? (data["metrics"]["sent"]["graphite"]["totalMillis"] - tmpgraphitevar[1]) : 0]);
                sent_time_data[5].push([new Date(data["stattime"]), tmpmemcachedvar[1] != 0 ? (data["metrics"]["sent"]["memcached"]["totalMillis"] - tmpmemcachedvar[1]) : 0]);
                sent_time_data[6].push([new Date(data["stattime"]), tmpriemannvar[1] != 0 ? (data["metrics"]["sent"]["riemann"]["totalMillis"] - tmpriemannvar[1]) : 0]);
                drawChart('Sent_time', sent_time_data);

                tmpsentallvar[0] = data["metrics"]["sent"]["all"]["num"];
                tmprrdtoolvar[0] = data["metrics"]["sent"]["rrdtool"]["num"];
                tmprrdcachedvar[0] = data["metrics"]["sent"]["rrdcached"]["num"];
                tmpgraphitevar[0] = data["metrics"]["sent"]["graphite"]["num"];
                tmpmemcachedvar[0] = data["metrics"]["sent"]["memcached"]["num"];
                tmpriemannvar[0] = data["metrics"]["sent"]["riemann"]["num"];

                tmpsentallvar[1] = data["metrics"]["sent"]["all"]["totalMillis"];
                tmprrdtoolvar[1] = data["metrics"]["sent"]["rrdtool"]["totalMillis"];
                tmprrdcachedvar[1] = data["metrics"]["sent"]["rrdcached"]["totalMillis"];
                tmpgraphitevar[1] = data["metrics"]["sent"]["graphite"]["totalMillis"];
                tmpmemcachedvar[1] = data["metrics"]["sent"]["memcached"]["totalMillis"];
                tmpriemannvar[1] = data["metrics"]["sent"]["riemann"]["totalMillis"];

                poll_data[1].push([new Date(data["stattime"]), tmppollokvar[0] != 0 ? (data["metrics"]["polls"]["ok"]["num"] - tmppollokvar[0]) : 0]);
                poll_data[2].push([new Date(data["stattime"]), tmppollfailvar[0] != 0 ? (data["metrics"]["polls"]["failed"]["num"] - tmppollfailvar[0]) : 0]);
                poll_data[3].push([new Date(data["stattime"]), tmppollmissvar != 0 ? (data["metrics"]["polls"]["misses"] - tmppollmissvar) : 0]);
                drawChart('Polls_min', poll_data);

                poll_time_data[1].push([new Date(data["stattime"]), tmppollokvar[1] != 0 ? (data["metrics"]["polls"]["ok"]["totalMillis"] - tmppollokvar[1]) : 0]);
                poll_time_data[2].push([new Date(data["stattime"]), tmppollfailvar[1] != 0 ? (data["metrics"]["polls"]["failed"]["totalMillis"] - tmppollfailvar[1]) : 0]);
                drawChart('Poll_time', poll_time_data);

                tmppollokvar[0] = data["metrics"]["polls"]["ok"]["num"];
                tmppollokvar[1] = data["metrics"]["polls"]["ok"]["totalMillis"];
                tmppollfailvar[0] = data["metrics"]["polls"]["failed"]["num"];
                tmppollfailvar[1] = data["metrics"]["polls"]["failed"]["totalMillis"];
                tmppollmissvar = data["metrics"]["polls"]["misses"];

                recv_data[1].push([new Date(data["stattime"]), tmprecvvar != 0 ? (data["metrics"]["received"]["all"] - tmprecvvar) : 0]);

                tmprecvvar = data["metrics"]["received"]["all"];
                drawChart('Received', recv_data);

                sumrz_data[1].push([new Date(data["stattime"]), tmpsumrzclustvar != 0 ? (data["metrics"]["summarize"]["cluster"] - tmpsumrzclustvar) : 0]);
                sumrz_data[2].push([new Date(data["stattime"]), tmpsumrzrootvar != 0 ? (data["metrics"]["summarize"]["root"] - tmpsumrzrootvar) : 0]);
                drawChart('Summarizations_min', sumrz_data);

                sumrz_time_data[1].push([new Date(data["stattime"]), tmpsumrzvar != 0 ? (data["metrics"]["summarize"]["totalMillis"] - tmpsumrzvar) : 0]);
                drawChart('Summarize_time', sumrz_time_data);

                tmpsumrzclustvar = data["metrics"]["summarize"]["cluster"];
                tmpsumrzrootvar = data["metrics"]["summarize"]["root"];
                tmpsumrzvar = data["metrics"]["summarize"]["totalMillis"];

                req_data[1].push([new Date(data["stattime"]), tmpreqallvar[0] != 0 ? (data["metrics"]["requests"]["all"]["num"] - tmpreqallvar[0]) : 0]);
                req_data[2].push([new Date(data["stattime"]), tmpinteractivevar[0] != 0 ? (data["metrics"]["requests"]["interactive"]["num"] - tmpinteractivevar[0]) : 0]);
                req_data[3].push([new Date(data["stattime"]), tmpxmlvar[0] != 0 ? (data["metrics"]["requests"]["xml"]["num"] - tmpxmlvar[0]) : 0]);
                drawChart('Requests', req_data);

                req_time_data[1].push([new Date(data["stattime"]), tmpreqallvar[1] != 0 ? (data["metrics"]["requests"]["all"]["totalMillis"] - tmpreqallvar[1]) : 0]);
                req_time_data[2].push([new Date(data["stattime"]), tmpinteractivevar[1] != 0 ? (data["metrics"]["requests"]["interactive"]["totalMillis"] - tmpinteractivevar[1]) : 0]);
                req_time_data[3].push([new Date(data["stattime"]), tmpxmlvar[1] != 0 ? (data["metrics"]["requests"]["xml"]["totalMillis"] - tmpxmlvar[1]) : 0]);
                drawChart('Requests_time', req_time_data);

                tmpreqallvar[0] = data["metrics"]["requests"]["all"]["num"];
                tmpreqallvar[1] = data["metrics"]["requests"]["all"]["totalMillis"];
                tmpinteractivevar[0] = data["metrics"]["requests"]["interactive"]["num"];
                tmpinteractivevar[1] = data["metrics"]["requests"]["interactive"]["totalMillis"];
                tmpxmlvar[0] = data["metrics"]["requests"]["xml"]["num"];
                tmpxmlvar[1] = data["metrics"]["requests"]["xml"]["totalMillis"];

                cpu_data[1].push([new Date(data["stattime"]), data["metrics"]["cpu"]["cpu_user"]]);
                cpu_data[2].push([new Date(data["stattime"]), data["metrics"]["cpu"]["cpu_nice"]]);
                cpu_data[3].push([new Date(data["stattime"]), data["metrics"]["cpu"]["cpu_system"]]);
                cpu_data[4].push([new Date(data["stattime"]), data["metrics"]["cpu"]["cpu_idle"]]);
                drawChart('Cpu', cpu_data);
            }

            function retrieveDropVal(txt){
                var e = document.getElementById(txt);
                return e.options[e.selectedIndex].value;
            }

            function updateMetrics(){
                if(document.getElementById("update").value == "Update"){
                    document.getElementById("update").value = "Stop";
                    $('#update').text("Stop");
                    getMetrics();
                    metricsTimerId = setInterval(getMetrics, metricsInterval);
                }else{
                    document.getElementById("update").value = "Update";
                    $('#update').text("Update");
                    setVars();
                    clearTimeout(metricsTimerId);
                    clearTimeout(lastTimeTimerId);
                }
            }

            function changetimespawn(){
                timespawn = retrieveDropVal("timespawn") * 60000; //mins
            }

            function begin(){
                setVars();
                lastTimeTimerId = setInterval(getLastTimes, lastTimeInterval);
                getLastTimes();
                updateMetrics();
            }

            function toSecondsAgo(val){
                return (($.now() - val)/1000).toFixed(1);
            }

            function last_timeCallback(data){
                /* 0 means no data received. */
                $("#last_poll_ok").text((data["metrics"]["polls"]["ok"]["lastTime"] != 0 ?
                            (toSecondsAgo(data["metrics"]["polls"]["ok"]["lastTime"]) > 1000 ? "> 15mins" : toSecondsAgo(data["metrics"]["polls"]["ok"]["lastTime"]) + "s" ) : "n/a"));
                $("#last_poll_fail").text((data["metrics"]["polls"]["failed"]["lastTime"] != 0 ?
                            (toSecondsAgo(data["metrics"]["polls"]["failed"]["lastTime"]) > 1000 ? "> 15mins" : toSecondsAgo(data["metrics"]["polls"]["failed"]["lastTime"]) + "s" ) : "n/a"));
                $("#last_summary").text((data["metrics"]["summarize"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["summarize"]["lastTime"]) + "s" : "n/a"));
                $("#last_rrd").text((data["metrics"]["sent"]["rrdtool"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["sent"]["rrdtool"]["lastTime"]) + "s" : "n/a"));
                $("#last_rrdcached").text((data["metrics"]["sent"]["rrdcached"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["sent"]["rrdcached"]["lastTime"]) + "s" : "n/a"));
                $("#last_graphite").text((data["metrics"]["sent"]["graphite"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["sent"]["graphite"]["lastTime"]) + "s" : "n/a"));
                $("#last_memcached").text((data["metrics"]["sent"]["memcached"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["sent"]["memcached"]["lastTime"]) + "s" : "n/a"));
                $("#last_riemann").text((data["metrics"]["sent"]["riemann"]["lastTime"] != 0 ? toSecondsAgo(data["metrics"]["sent"]["riemann"]["lastTime"]) + "s" : "n/a"));
            }
            $(document).ready(function() {
                begin();
            });
        </script>
    </head>
    <body>
        <div id="buttons">
            <button type="button" id="update" value="Update" onclick="updateMetrics()">Update</button>
            <label>
                <select id="timespawn" onchange="changetimespawn()">
                    <option value=10>10</option>
                    <option value=20>20</option>
                    <option value=30>30</option>
                    <option value=60>60</option>
                    <option value=120>120</option>
                </select>
                Timespawn (min)
            </label>
        </div>

        <!-- Last Times -->
        <table class='lasts'>
            <tr>
            <td>Last Poll Ok:</td>
            <td width=55px><span id="last_poll_ok">...</span></td>
            <td>Poll Failed:</td>
            <td width=55px><span id="last_poll_fail">...</span></td>
            <td>Summary:</td>
            <td width=55px><span id="last_summary">...</span></td>
            <td>RRD:</td>
            <td width=55px><span id="last_rrd">...</span></td>
            <td>RRDcached:</td>
            <td width=55px><span id="last_rrdcached">...</span></td>
            <td>Graphite:</td>
            <td width=55px><span id="last_graphite">...</span></td>
            <td>Memcached:</td>
            <td width=55px><span id="last_memcached">...</span></td>
            <td>Riemann:</td>
            <td width=55px><span id="last_riemann">...</span></td>
            </tr>
        </table>
        <!--End Last Times -->

        <!-- Graphs -->
        <div class="container">
            <h1>Polls/min</h1>
            <div id="Polls_min" class="placeholder"></div>
            <h1>Received</h1>
            <div id="Received" class="placeholder"></div>
            <h1>Summarizations/min</h1>
            <div id="Summarizations_min" class="placeholder"></div>
            <h1>Sent</h1>
            <div id="Sent" class="placeholder"></div>
            <h1>Requests</h1>
            <div id="Requests" class="placeholder"></div>
            <h1>Poll time</h1>
            <div id="Poll_time" class="placeholder"></div>
            <h1>Sent time</h1>
            <div id="Sent_time" class="placeholder"></div>
            <h1>Summarize time</h1>
            <div id="Summarize_time" class="placeholder"></div>
            <h1>Requests time</h1>
            <div id="Requests_time" class="placeholder"></div>
            <h1>Cpu</h1>
            <div id="Cpu" class="placeholder"></div>
        </div>
        <!--End Graphs -->
        <div id='tooltip'></div>
    </body>
</html>